/**
* <p>Title: FindElementUtil.java</p>
* <p>Description: 元素定位、加载utils</p>
* <p>Company: www.huoyunren.com</p>
* @author duanxiangyun
* @date 2015年1月7日
* @version 1.0
*/
package com.hxbd.test.utils.webdriver;

import java.util.List;

import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.TimeoutException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.testng.Assert;
import com.google.common.base.Function;
import com.hxbd.test.handles.PageElementHandler;

/**
 * 元素识别公共方法封装类
 */
public class FindElementUtil {
	private static WebElement we;
	//driverwait的等待时间
	private static int driveWaitTime = 30000;
//	= Integer.parseInt(PageElementHandler.getStoreSettingProperties().getProperty("driver_waitTime"));
	
	public static int getDriveWaitTime() {
		return driveWaitTime;
	}
	public static void setDriveWaitTime(int driveWaitTime) {
		FindElementUtil.driveWaitTime = driveWaitTime;
	}
	
	/**
	 * 元素是否存在
	 * @param driver WebDriver
	 * @param by By
	 * @return boolean
	 */
	public static boolean isElementPresent(WebDriver driver, By by) { 
	    try { 
//	    	driver.manage().timeouts().implicitlyWait(implicitlyWaitTime, TimeUnit.SECONDS); 
	    	driver.findElement(by); 
	    	return true; 
	    } catch (NoSuchElementException e) { 
	      return false; 
	    } 
	  }
	/**
	 * 元素是否可见
	 * @param element WebElement
	 * @return boolean
	 */
	public static boolean isElementDisplayed(final WebElement element) {
            return element.isDisplayed();
    }
	
	/**
	 * 元素是否存在
	 * @param driver WebDriver
	 * @param we WebElement
	 * @param by By
	 * @return boolean
	 */
	public static boolean isElementPresent(WebDriver driver, WebElement we, By by) { 
	    
    	try { 
//    		driver.manage().timeouts().implicitlyWait(implicitlyWaitTime, TimeUnit.SECONDS); 
        	we.findElement(by); 
	    	return true; 
	    } catch (NoSuchElementException e) { 
	      return false; 
	    } 
	    
	  }

//	public static Boolean isElementPresent (final WebDriver driver, final By by) {
//		WebDriverWait wait = new WebDriverWait(driver, 30);
//  	  //创建一个新的ExpecctedCondition接口，就必须实现apply方法
//  	  Boolean flag = wait.until
//  			  (new ExpectedCondition<Boolean> (){
//  	  public Boolean apply(WebDriver d){
//  	  return isElementPresentTemp(driver,by);
//  	  }
//  	  });
//  	  return flag;
//	}
//	
	public static Boolean isEleDisplayAndPresent (WebDriver driver, final WebElement we) {
	  WebDriverWait wait = new WebDriverWait(driver, driveWaitTime);
  	  Boolean flag = wait.until
  			  (new ExpectedCondition<Boolean> (){
  	  public Boolean apply(WebDriver d){
  	  return isElementDisplayed(we);
  	  }
  	  });
  	  return flag;
	}
	/**
	 * 存在并可见
	 * @param driver WebDriver
	 * @param by By
	 * @return Boolean
	 */
	public static Boolean isElementPresentAndDisplayed (final WebDriver driver, By by) {
		Boolean flag;
		if (isElementPresent(driver, by) &&
				isElementDisplayed(driver.findElement(by))) {
			
			flag = true;
		}
		else {
			flag = false;
		}
		return flag;
	}
	/**
	 * 显示等待60s，直到元素不存在或者不可见
	 * @param driver
	 * @param we
	 * @return Boolean
	 */
	public static Boolean waitEleInvisible(WebDriver driver,final WebElement we)
    {
		WebDriverWait wait = new WebDriverWait(driver, driveWaitTime);
		Boolean flag;
		try {
			flag = wait.until
	  			  (new ExpectedCondition<Boolean>() {

					@Override
					public Boolean apply(WebDriver arg0) {
						// TODO Auto-generated method stub
						Boolean tmp = true;
						try {
							tmp = we.isDisplayed();
						}catch(NoSuchElementException ex) {
							tmp = false;
						}
						return !tmp;
					}
				});
		}catch (TimeoutException e) {
			flag = false;
		}
		return flag;
    }
//	/**
//	 * 等待弹窗出现
//	 * @param driver
//	 * @return
//	 */
//	public static Boolean waitAlertVisible (WebDriver driver) {
//		WebDriverWait wait = new WebDriverWait(driver, driveWaitTime);
//		Boolean flag;
//		try {
//			flag = wait.until
//	  			  (ExpectedConditions.not(ExpectedConditions.alertIsPresent()));
//		}catch (TimeoutException e) {
//			flag = false;
//		}
//		return flag;
//	}
//	/**
//	 * 显示等待，直到元素不存在或者不可见
//	 * @param we
//	 * @param waitsec 等待时间
//	 */
//	public static void waitEleDisappear (WebElement we, long waitsec) {
//		for (int i = 1; i <= waitsec; i++) {
//			try {
//				if (we.isDisplayed()) {
//					Thread.sleep(1000);
//				}
//				else {				
//					break;
//				}
//			}
//			catch (NoSuchElementException e) {
//				break;
//			} catch (InterruptedException e) {
//				// TODO Auto-generated catch block
//				e.printStackTrace();
//			}
//		}
//	}
//	
//	/**
//	 * 显示等待60s，直到元素不存在或者不可见
//	 * @param we
//	 */
//	public static void waitEleDisappear (WebElement we) {
//		waitEleDisappear(we, 60);
//	}
//	/**
//	 * 等待元素可点击
//	 * @param driver WebDriver
//	 * @param by By
//	 * @return WebElement
//	 */
	public static WebElement waitElementClickable (WebDriver driver, By by) {
		WebDriverWait wait = new WebDriverWait(driver, driveWaitTime);
  	  //创建一个新的ExpecctedCondition接口，就必须实现apply方法
  	  WebElement flag = wait.until
  			  (ExpectedConditions.elementToBeClickable(by));
  	  return flag;
	}
	/**
	 * 
	 * @param driver
	 * @param ele
	 * @return WebElement
	 */
	public static WebElement waitElementClickable (WebDriver driver,WebElement ele) {
		WebDriverWait wait = new WebDriverWait(driver, driveWaitTime);
  	  //创建一个新的ExpecctedCondition接口，就必须实现apply方法
	  waitElementDisPlays(driver, ele);
  	  WebElement flag = wait.until
  			  (ExpectedConditions.elementToBeClickable(ele));
  	  return flag;
	}
	/**
	 * 等待元素可点击:自定义等待时间
	 * @param driver WebDriver
	 * @param by By
	 * @param time 等待时间
	 * @return WebElement
	 */
	public static WebElement waitElementClickable (WebDriver driver, By by, Long time) {
		WebDriverWait wait = new WebDriverWait(driver, time);
		waitElementDisPlays(driver, by);
  	  	WebElement flag = wait.until
  			  (ExpectedConditions.elementToBeClickable(by));
  	  	return flag;
	}
	/**
	 * 根据title等待页面出现，超时时间driveWaitTime
	 * @param driver
	 * @param title
	 * @return  boolean
	 */
	public static boolean waitPageLoadedForTitle (WebDriver driver,String title) {
		WebDriverWait wait = new WebDriverWait(driver, driveWaitTime);
		Boolean flag;
		try {
			flag = wait.until(ExpectedConditions.titleContains(title));
		}
		catch (TimeoutException e) {
			flag = false;
		}
		return flag;
	}
	/**
	 * 60s内等待iframe出现并切换到改iframe
	 * @param driver 切换前的WebDriver
	 * @param by By
	 * @return WebDriver 切换后的driver
	 */
	public static WebDriver waitframeToBeAvailableAndSwitchToIt (WebDriver driver, By by) {
		try {
			WebDriverWait wait = new WebDriverWait(driver, driveWaitTime);
			WebDriver dr = wait.until(ExpectedConditions.frameToBeAvailableAndSwitchToIt(by));
			return dr;
		}
		catch (TimeoutException e) {
    		return null;
    	}
	}

    /**
     * 显示等待:自定义等待时间
     * @param driver WebDriver
     * @param time 等待时间
     * @param by By
     * @return WebElement
     */
    public static WebElement waitElementAppear(WebDriver driver, long time, final By by) {
    	WebDriverWait wait = new WebDriverWait(driver, time);
    	  //创建一个新的ExpecctedCondition接口，就必须实现apply方法
		WebElement message = wait.until
				  (new ExpectedCondition<WebElement>(){
		public WebElement apply(WebDriver d){
		return d.findElement(by);
    	  }
    	  });
    	  return message;
    }
    
    /**
     * 显示等待元素出现
     * @param driver WebDriver
     * @param by By
     * @return WebElement
     * @throws TimeoutException
     */
    public static WebElement waitElementAppear(WebDriver driver, final By by) throws TimeoutException{
    	WebDriverWait wait = new WebDriverWait(driver, driveWaitTime);
    	  //创建一个新的ExpecctedCondition接口，就必须实现apply方法
    	  WebElement message = wait.until
    			  (new ExpectedCondition<WebElement>(){
    	  public WebElement apply(WebDriver d){
    	  return d.findElement(by);
    	  }
    	  });
    	  return message;
    }
    /**
     * 显示等待元素出现
     * @param driver WebDriver
     * @param we WebElement
     * @param by By
     * @return WebElement
     * @throws TimeoutException
     */
    public static WebElement waitElementAppear(WebDriver driver, final WebElement we, final By by) throws TimeoutException{
    	WebDriverWait wait = new WebDriverWait(driver, driveWaitTime);
    	  //创建一个新的ExpecctedCondition接口，就必须实现apply方法
    	  WebElement message = wait.until
    			  (new ExpectedCondition<WebElement>(){
    	  public WebElement apply(WebDriver d){
    	  return we.findElement(by);
    	  }
    	  });
    	  return message;
    }
    /**
     * 60秒内显示等待元素出现,不出现返回NULL
     * @param driver WebDriver
     * @param by By
     * @return WebElement or null
     */
    public static WebElement waitElementAppears(WebDriver driver, final By by) {
    	try {
    		WebDriverWait wait = new WebDriverWait(driver, driveWaitTime);
      	  //创建一个新的ExpecctedCondition接口，就必须实现apply方法
      	  	WebElement message = wait.until
      			  (new ExpectedCondition<WebElement>(){
      	    public WebElement apply(WebDriver d){
      	    return d.findElement(by);
      	    }
      	    });
      	    return message;
    	}
    	catch (TimeoutException e) {
    		return null;
    	}
    }
   /**
    * 等待元素出现，在 driveWaitTime时间范围内
    * @param driver WebDriver
    * @param we WebElement
    */
    public static void waitElementDisPlay (WebDriver driver,final WebElement we) {
		WebDriverWait wait = new WebDriverWait(driver, driveWaitTime);
  	  //创建一个新的ExpecctedCondition接口，就必须实现apply方法
  	  	Boolean message = wait.until
  			  (new ExpectedCondition<Boolean>() {/* (non-Javadoc)
  			 * @see com.google.common.base.Function#apply(java.lang.Object)
  			 */
			@Override
			public Boolean apply(WebDriver d) {
				// TODO Auto-generated method stub
				return we.isDisplayed();
      	    }
      	    });
    }
    /**
     * 
     * 等待元素出现，在 driveWaitTime时间范围内
     * @param driver WebDriver
     * @param we WebElement
     * @return boolean: 60s未出现返回false.
     */
    public static boolean waitElementDisPlays (WebDriver driver,final WebElement we) {
    	try {
			WebDriverWait wait = new WebDriverWait(driver, driveWaitTime);
			  //创建一个新的ExpecctedCondition接口，就必须实现apply方法
		  	Boolean message = wait.until
				  (new ExpectedCondition<Boolean>() {/* (non-Javadoc)
				 * @see com.google.common.base.Function#apply(java.lang.Object)
				 */
			@Override
			public Boolean apply(WebDriver d) {
				// TODO Auto-generated method stub
				return we.isDisplayed();
			    }
			    });
		  	return message;
    	}catch (TimeoutException e) {
    		return false;
    	}
      }
    /**
     * 等待元素出现，在 driveWaitTime时间范围内
     * @param driver
     * @param by
     * @return boolean
     */
    public static boolean waitElementDisPlays (WebDriver driver,By by) {
    	try {
			WebDriverWait wait = new WebDriverWait(driver, driveWaitTime);
			  //创建一个新的ExpecctedCondition接口，就必须实现apply方法
		  	WebElement message = wait.until
				  (ExpectedConditions.visibilityOfElementLocated(by));
		  	return true;
    	}catch (TimeoutException e) {
    		return false;
    	}
      }
    /**
     * 
     * 等待元素出现，在 time时间范围内
     * @param driver WebDriver
     * @param we WebElement
     * @param time 等待时间
     * @return boolean: time时间内未出现返回false.
     */
    public static boolean waitElementDisPlays (WebDriver driver,final WebElement we, long time) {
    	try {
			WebDriverWait wait = new WebDriverWait(driver, time);
			  //创建一个新的ExpecctedCondition接口，就必须实现apply方法
		  	Boolean message = wait.until
				  (new ExpectedCondition<Boolean>() {/* (non-Javadoc)
				 * @see com.google.common.base.Function#apply(java.lang.Object)
				 */
			@Override
			public Boolean apply(WebDriver d) {
				// TODO Auto-generated method stub
				return we.isDisplayed();
			    }
			    });
		  	return message;
    	}catch (TimeoutException e) {
    		return false;
    	}
      }
    /**
     * 自定义时间显示等待元素出现,不出现返回NULL
     * @param driver WebDriver
     * @param time 等待时间
     * @param by By
     * @return WebElement
     */
    public static WebElement waitElementAppears(WebDriver driver, long time,  final By by) {
    	try {
    		WebDriverWait wait = new WebDriverWait(driver, time);
      	  //创建一个新的ExpecctedCondition接口，就必须实现apply方法
      	  	WebElement message = wait.until
      			  (new ExpectedCondition<WebElement>(){
      	    public WebElement apply(WebDriver d){
      	    return d.findElement(by);
      	    }
      	    });
      	    return message;
    	}
    	catch (TimeoutException e) {
    		return null;
    	}
    }
    /**
     * 60秒内显示等待元素集出现
     * @param driver WebDriver
     * @param by By
     * @return 元素列表
     */
    public static List<WebElement> waitElementsAppear(WebDriver driver, final By by) {
    	WebDriverWait wait = new WebDriverWait(driver, driveWaitTime);
    	  //创建一个新的ExpecctedCondition接口，就必须实现apply方法
    	List<WebElement> message = wait.until
    			  (ExpectedConditions.presenceOfAllElementsLocatedBy(by));
    	  return message;
    }
    /**
     * 在元素集中根据文本获取元素
     * @param EleName 待查询元素文本
     * @param checkInelements 所查询的元素集
     * @return WebElement
     */
    public static WebElement getElementByName(String EleName, List<WebElement> checkInelements) {
    	for (WebElement e : checkInelements) {
    		if (e.getText().equals(EleName)) {
    			we = e;
    			break;
    		}
    	}
		return we;
    }

    /**
     * 切换到iframe
     * @param driver WebDriver
     * @param iframeId iframe xpathid
     */
    public static void switchToIframe (WebDriver driver,String iframeId) {
		WebElement iframe = waitElementAppear(driver, By.id(iframeId));
		driver.switchTo().frame(iframe);
	}
    
    public static void switchToIframeXpath (WebDriver driver,String iframexpath) {
		WebElement iframe = waitElementAppear(driver, By.xpath(iframexpath));
		driver.switchTo().frame(iframe);
	}
    /**
     * 跳转到有table的界面时，等待table出现
     * @param driver WebDriver
     * @param ifameId iframe xpathid
     * @param tableby 当前表的xpath By
     */
    public static void waitTableapears (WebDriver driver,String ifameId, By tableby) {
    	switchToIframe(driver, ifameId);
		try {
			isElementDisplayed(waitElementAppear(driver, tableby));
		}catch (Exception e) {
			Assert.fail("列表超时加载");
		}
    }
    
    /**
     * 等待table出现
     * @param driver WebDriver
     * @param tableby 当前表的xpath By
     */
    public static void waitTableapear2 (WebDriver driver,By tableby) {
		try {
			isElementDisplayed(waitElementAppear(driver, tableby));
		}catch (Exception e) {
			Assert.fail("列表超时加载");
		}
    }
   /**
    * 页面是否加载完？ 
    * @return Boolean
    */
    protected static Function<WebDriver, Boolean> isPageLoaded() {
    	return new Function<WebDriver, Boolean>() {
	    	@Override
	    	public Boolean apply(WebDriver driver) {
	    		return ((JavascriptExecutor) driver).executeScript("return document.readyState").equals("complete");
	    	}
	    };
    }
    /**
     * 等待页面加载完成
     * @param driver webdriver
     */
	public static void waitForPageLoad(WebDriver driver) {
		WebDriverWait wait = new WebDriverWait(driver, driveWaitTime);
		wait.until(isPageLoaded());
	}
}
